import {isNone, funThrottleByTime} from 'st-common-core'
import {ResType} from '../../res/types/res-type.ts'
import {ResObjPropNameConst} from '../../res/consts/res-prop-name-const.ts'

/**
 * 生成通过请求获取数据的处理函数
 *
 * @template T 数据类型
 * @param {(filters?: Record<string, any>) => Promise<ResType>} getDataApi 请求获取数据的 API 函数，调用该函数时，会向该函数传递一
 * 个对象类型的参数，该参数为通过获取数据时的筛选过滤条件
 * @param {(data: T) => void} setData 保存数据的处理函数，该函数接收通过请求获取的数据作为参数
 * @param {(value: boolean) => void} setLoading 设置是否为加载状态的处理函数，只有传递了该函数参数时，才会调用该函数设置加载状态，调用该函
 * 数时，会传入一个布尔类型的参数，该参数为是否为加载状态，true 为加载状态，false 为结束加载状态
 * @param {number} funThrottleTime 对生成的通过请求获取数据的处理函数进行节流处理的时间间隔，单位为毫秒，默认为 1000 毫秒
 * @returns {(filters?: Record<string, any>) => Promise<ResType>} 通过请求获取数据的处理函数，生成的函数可以接收一个对象类型的参数，该
 * 参数为通过获取数据时的筛选过滤条件，生成的函数的返回值是一个包含 {@link ResType} 类型数据的 Promise 对象
 */
export const genGetDataByReqHandler = <T>(
  {
    getDataApi,
    setData,
    setLoading,
    funThrottleTime = 1000,
  }: {
    getDataApi: (filters?: Record<string, any>) => Promise<ResType>;
    setData: (data: T) => Promise<void>;
    setLoading?: (value: boolean) => void;
    funThrottleTime?: number;
  }
) => {
  // 通过请求获取数据的处理函数
  const getDataByReqHandler = async (filters: Record<string, any> = {}): Promise<ResType> => {
    // 如果设置加载状态的函数不为空，则调用该函数，设置为加载状态
    if (!isNone(setLoading)) (setLoading as (value: boolean) => void)(true)
    // 发送请求获取数据
    return getDataApi(filters)
      .then(async (res: ResType) => {
        // 如果获取失败
        if (!res[ResObjPropNameConst.STATUS]) return res
        // 如果获取成功，保存数据
        await setData(res[ResObjPropNameConst.DATA] as T)
        // 返回响应结果
        return res
      })
      .finally(() => {
        // 如果设置加载状态的函数不为空，则调用该函数，设置结束加载状态
        if (!isNone(setLoading)) (setLoading as (value: boolean) => void)(false)
      })
  }
  // 对通过请求获取数据的处理函数进行节流处理
  return funThrottleByTime({
    fun: getDataByReqHandler,
    interval: funThrottleTime,
  }) as typeof getDataByReqHandler
}
